﻿using AutoMapper;
using DFGK.IRepository;
using DFGK.IService;
using DFGK_WMS.Model.Enum;
using DFGK_WMS.Model.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace DFGK.Service
{
    public class BarCodeRuleService : BaseService, IBarCodeRuleService
    {
        private readonly ITransferBinOrderDetailRepository _transferBinOrderDetailRepository;
        private readonly IReceivingOrderDetailRepository _receivingOrderDetailRepository;
        private readonly IShippingOrderDetailRepository _shippingOrderDetailRepository;
        private readonly IStocktakingOrderRepository _stocktakingOrderRepository;
        private readonly IReceivingBillRepository _receivingBillRepository;
        private readonly IBarCodeRuleRepository _barCodeRuleRepository;
        private readonly IPalletRepository _palletRepository;
        private readonly IUnitOfWork _unitOfWork;
        public BarCodeRuleService(IMapper mapper, IBarCodeRuleRepository _barCodeRuleRepository, IUnitOfWork unitOfWork, IReceivingOrderDetailRepository receivingOrderDetailRepository, IPalletRepository _palletRepository, IShippingOrderDetailRepository shippingOrderDetailRepository, IReceivingBillRepository receivingBillRepository, IStocktakingOrderRepository _stocktakingOrderRepository, ITransferBinOrderDetailRepository _transferBinOrderDetailRepository) : base(mapper)
        {
            this._transferBinOrderDetailRepository = _transferBinOrderDetailRepository;
            this._stocktakingOrderRepository = _stocktakingOrderRepository;
            this._barCodeRuleRepository = _barCodeRuleRepository;
            this._palletRepository = _palletRepository;
            _receivingOrderDetailRepository = receivingOrderDetailRepository;
            _shippingOrderDetailRepository = shippingOrderDetailRepository;
            _receivingBillRepository = receivingBillRepository;
            _unitOfWork = unitOfWork;
        }

        public bool AddCodeRule(BarCodeRule dto)
        {
            string code = "BarCodeRules";
            var aobj = _barCodeRuleRepository.GetEntityWhereAll(x => x.Code.Contains(code)).OrderByDescending(x => x.CreateDate).FirstOrDefault();
            if (aobj != null)
            {
                string pattern = @"\d+";
                MatchCollection matches = Regex.Matches(aobj.Code, pattern);
                string value = matches[matches.Count - 1].Value;
                int values = Convert.ToInt32(value);
                values++;
                dto.Code = code + values.ToString("D4");
            }
            else
            {
                int i = 1;
                dto.Code = code + i.ToString("D4");
            }

            var bobj = _barCodeRuleRepository.QueryIsEntityWhere(x => x.Type == dto.Type);
            if (bobj != null)
            {
                return false;
            }
            foreach (var item in Enum.GetValues<CodeRulesType>())
            {
                if (item == (CodeRulesType)dto.Type)
                {
                    dto.Code = item.ToString();
                }
            }

            dto.Sample = GetBarCodeSample(dto, out int isnumber);
            _barCodeRuleRepository.AddEntity(dto);
            return _unitOfWork.SaveChangesEntity();
        }
        /// <summary>
        /// 静态方法获取编码规则
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        private static string GetBarCodeSample(BarCodeRule m, out int isnumber)
        {
            isnumber = 0;
            var result = new StringBuilder();
            DateTime date = DateTime.Now;
            var barcoderules = m.BarCodeRules.Split(',');

            foreach (var item in barcoderules)
            {
                switch (Convert.ToInt32(item))
                {
                    case 0:
                        int startIndex = m.RuleDescription.IndexOf("%文本框") + "%文本框".Length;
                        int endIndex = m.RuleDescription.IndexOf("%", startIndex);

                        if (startIndex != -1 && endIndex != -1)
                        {
                            string tpw = m.RuleDescription.Substring(startIndex, endIndex - startIndex);
                            result.Append(tpw);
                        }
                        else
                        {
                            result.Append("文本框有误！");
                        }
                        break;
                    case 1:
                        result.Append(date.ToString("yyyy"));
                        break;
                    case 2:
                        result.Append(date.ToString("MM"));
                        break;
                    case 3:
                        result.Append(date.ToString("dd"));
                        break;
                    case 4:
                        result.Append(date.ToString("HH"));
                        break;
                    case 5:
                        int weeknow = (int)date.DayOfWeek;
                        if (weeknow == 0)
                        {
                            result.Append(7);
                        }
                        else
                        {
                            result.Append(weeknow);
                        }
                        break;
                    case 6:
                        string year = date.ToString("yyyy");
                        result.Append(year.Substring(2, 2));
                        break;
                    case 7:
                        isnumber = 1;
                        break;
                    default:
                        result = null;
                        break;
                }
            }
            return result?.ToString();
        }
        public bool DelCodeRule(long ids)
        {
            var rules = _barCodeRuleRepository.QueryEntityById(ids);
            if (rules != null)
            {
                _barCodeRuleRepository.DelEntity(rules);
                return _unitOfWork.SaveChangesEntity();
            }
            return false;
        }

        public string? GetBarCodeSample(int type)
        {
            var bobj = _barCodeRuleRepository.QueryIsEntityWhere(x => x.Type == type && x.IsEnable == true);
            int isnumber = 0;
            if (bobj != null)
            {
                string value = GetBarCodeSample(bobj, out isnumber) ?? "此处有误！";
                string result = "";

                switch (type)
                {
                    case 0:
                        break;
                    case 1:
                        result = GetInOrderBarCode(result, value, isnumber, bobj.NumberLength);
                        if (!string.IsNullOrEmpty(result))
                        {
                            return result;
                        }
                        break;
                    case 2:
                        result = GetOutOrderBarCode(result, value, isnumber, bobj.NumberLength);
                        if (!string.IsNullOrEmpty(result))
                        {
                            return result;
                        }
                        break;
                    case 3:
                        break;
                    case 4:
                        break;
                    case 5:
                        break;
                    case 6:
                        result = GetTranOrderBarCode(result, value, isnumber, bobj.NumberLength);
                        if (!string.IsNullOrEmpty(result))
                        {
                            return result;
                        }
                        break;
                    case 7:
                        result = GetDiscOrderBarCode(result, value, isnumber, bobj.NumberLength);
                        if (!string.IsNullOrEmpty(result))
                        {
                            return result;
                        }
                        break;
                    default:
                        break;
                }
            }

            return null;
        }

        public BarCodeRule? GetCodeRule(long id)
        {
            return _barCodeRuleRepository.QueryEntityById(id);
        }

        public List<BarCodeRule> GetCodeRules(string? name, int pageIndex, int pageSize, out int totalCount)
        {
            var list = _barCodeRuleRepository.GetEntityAlls();
            if (!string.IsNullOrEmpty(name))
            {
                list = list.Where(x => x.Name.Contains(name));
            }
            var lists = _barCodeRuleRepository.GetEntityAlls(list, pageIndex, pageSize, out totalCount, x => x.CreateDate, false);
            return lists.ToList();
        }

        public bool UpdateCodeRule(BarCodeRule dto)
        {
            var bobj = _barCodeRuleRepository.QueryIsEntityWhere(x => x.Id != dto.Id && x.Type == dto.Type);
            if (bobj != null)
            {
                return false;
            }

            foreach (var item in Enum.GetValues<CodeRulesType>())
            {
                if (item == (CodeRulesType)dto.Type)
                {
                    dto.Code = item.ToString();
                }
            }
            dto.Sample = GetBarCodeSample(dto, out int isnumber);
            _barCodeRuleRepository.UpdEntity(dto);
            return _unitOfWork.SaveChangesEntity();
        }

        #region
        /// <summary>
        /// 入库单编码
        /// </summary>
        /// <param name="result"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private string GetInOrderBarCode(string result, string value, int isnumber, int? numberLength)
        {
            if (isnumber == 0)
                return value;
            for (int i = 1; ; i++)
            {
                string iStr = i.ToString($"D{numberLength ?? 1}");
                result = $"{value}{iStr}";
                var obj = _receivingBillRepository.QueryIsEntityWhere(x => x.BillNo == result);
                if (obj != null)
                {
                    continue;
                }
                else
                {
                    return result;
                }
            }
        }

        /// <summary>
        /// 出库单编码
        /// </summary>
        /// <param name="result"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private string GetOutOrderBarCode(string result, string value, int isnumber, int? numberLength)
        {
            if (isnumber == 0)
                return value;
            for (int i = 1; ; i++)
            {
                string iStr = i.ToString($"D{numberLength ?? 1}");
                result = $"{value}{iStr}";
                var obj = _shippingOrderDetailRepository.QueryIsEntityWhere(x => x.OrderSn == result);
                if (obj != null)
                {
                    continue;
                }
                else
                {
                    return result;
                }
            }
        }


        /// <summary>
        /// 移库单编码
        /// </summary>
        /// <param name="result"></param>
        /// <param name="value"></param>
        /// <param name="numberLength"></param>
        /// <returns></returns>
        private string GetTranOrderBarCode(string result, string value, int isnumber, int? numberLength)
        {
            if (isnumber == 0)
                return value;
            for (int i = 1; ; i++)
            {
                string iStr = i.ToString($"D{numberLength ?? 1}");
                result = $"{value}{iStr}";
                var obj = _transferBinOrderDetailRepository.QueryIsEntityWhere(x => x.OrderSn == result);
                if (obj != null)
                {
                    continue;
                }
                else
                {
                    return result;
                }
            }
        }

        /// <summary>
        /// 盘点单编码
        /// </summary>
        /// <param name="result"></param>
        /// <param name="value"></param>
        /// <param name="numberLength"></param>
        /// <returns></returns>
        private string GetDiscOrderBarCode(string result, string value, int isnumber, int? numberLength)
        {
            if (isnumber == 0)
                return value;
            for (int i = 1; ; i++)
            {
                string iStr = i.ToString($"D{numberLength ?? 1}");
                result = $"{value}{iStr}";
                var obj = _stocktakingOrderRepository.QueryIsEntityWhere(x => x.OrderSn == result);
                if (obj != null)
                {
                    continue;
                }
                else
                {
                    return result;
                }
            }
        }
        #endregion
    }
}
